home *** CD-ROM | disk | FTP | other *** search
/ Micromanía 92 / CDMM92_1.ISO / SOF 2 SDK / sof2sdk-101.msi / _92D6AC311BB48EBA344BBABC89DA6AB0 / _92B6DA498046483BA8E7038D40F52C9F < prev    next >
Encoding:
Text File  |  2002-06-05  |  13.7 KB  |  595 lines

  1. // Copyright (C) 2001-2002 Raven Software.
  2. //
  3. // cg_localents.c -- every frame, generate renderer commands for locally
  4. // processed entities, like smoke puffs, shells, etc.
  5.  
  6. #include "cg_local.h"
  7.  
  8. #define    MAX_LOCAL_ENTITIES    512
  9. localEntity_t    cg_localEntities[MAX_LOCAL_ENTITIES];
  10. localEntity_t    cg_activeLocalEntities;        // double linked list
  11. localEntity_t    *cg_freeLocalEntities;        // single linked list
  12.  
  13. /*
  14. ===================
  15. CG_InitLocalEntities
  16.  
  17. This is called at startup and for map restarts
  18. ===================
  19. */
  20. void CG_InitLocalEntities( void ) 
  21. {
  22.     int        i;
  23.  
  24.     memset( cg_localEntities, 0, sizeof( cg_localEntities ) );
  25.     cg_activeLocalEntities.next = &cg_activeLocalEntities;
  26.     cg_activeLocalEntities.prev = &cg_activeLocalEntities;
  27.     cg_freeLocalEntities = cg_localEntities;
  28.     
  29.     for ( i = 0 ; i < MAX_LOCAL_ENTITIES - 1 ; i++ ) 
  30.     {
  31.         cg_localEntities[i].next = &cg_localEntities[i+1];
  32.     }
  33. }
  34.  
  35.  
  36. /*
  37. ==================
  38. CG_FreeLocalEntity
  39. ==================
  40. */
  41. void CG_FreeLocalEntity( localEntity_t *le ) 
  42. {
  43.     if ( !le->prev ) 
  44.     {
  45.         Com_Error( ERR_FATAL, "CG_FreeLocalEntity: not active" );
  46.     }
  47.  
  48.     if (le->refEntity.ghoul2)
  49.     {
  50.         trap_G2API_CleanGhoul2Models(&le->refEntity.ghoul2);
  51.     }
  52.  
  53.     // remove from the doubly linked active list
  54.     le->prev->next = le->next;
  55.     le->next->prev = le->prev;
  56.  
  57.     // the free list is only singly linked
  58.     le->next = cg_freeLocalEntities;
  59.     cg_freeLocalEntities = le;
  60. }
  61.  
  62. /*
  63. ===================
  64. CG_AllocLocalEntity
  65.  
  66. Will allways succeed, even if it requires freeing an old active entity
  67. ===================
  68. */
  69. localEntity_t    *CG_AllocLocalEntity( void ) {
  70.     localEntity_t    *le;
  71.  
  72.     if ( !cg_freeLocalEntities ) {
  73.         // no free entities, so free the one at the end of the chain
  74.         // remove the oldest active entity
  75.         CG_FreeLocalEntity( cg_activeLocalEntities.prev );
  76.     }
  77.  
  78.     le = cg_freeLocalEntities;
  79.     cg_freeLocalEntities = cg_freeLocalEntities->next;
  80.  
  81.     memset( le, 0, sizeof( *le ) );
  82.  
  83.     // link into the active list
  84.     le->next = cg_activeLocalEntities.next;
  85.     le->prev = &cg_activeLocalEntities;
  86.     cg_activeLocalEntities.next->prev = le;
  87.     cg_activeLocalEntities.next = le;
  88.     return le;
  89. }
  90.  
  91.  
  92. /*
  93. ====================================================================================
  94.  
  95. FRAGMENT PROCESSING
  96.  
  97. A fragment localentity interacts with the environment in some way (hitting walls),
  98. or generates more localentities along a trail.
  99.  
  100. ====================================================================================
  101. */
  102.  
  103.  
  104. /*
  105. ================
  106. CG_FragmentBounceMark
  107. ================
  108. */
  109. void CG_FragmentBounceMark( localEntity_t *le, trace_t *trace ) {
  110.     int            radius;
  111.  
  112.     if ( le->leMarkType == LEMT_BLOOD ) 
  113.     {
  114.         radius = 16 + (rand()&31);
  115.  
  116.         trap_R_AddDecalToScene ( cgs.media.bloodMarkShader, trace->endpos, 
  117.                                  trace->plane.normal, random()*360,
  118.                                  1,1,1,1, qtrue, radius, qfalse );
  119.  
  120.     } 
  121.     else if ( le->leMarkType == LEMT_BURN ) 
  122.     {
  123.         radius = 8 + (rand()&15);
  124.  
  125.         trap_R_AddDecalToScene ( cgs.media.burnMarkShader, trace->endpos, 
  126.                                  trace->plane.normal, random()*360,
  127.                                  1,1,1,1, qtrue, radius, qfalse );
  128.     }
  129.  
  130.  
  131.     // don't allow a fragment to make multiple marks, or they
  132.     // pile up while settling
  133.     le->leMarkType = LEMT_NONE;
  134. }
  135.  
  136. /*
  137. ================
  138. CG_FragmentBounceSound
  139. ================
  140. */
  141. void CG_FragmentBounceSound( localEntity_t *le, trace_t *trace ) 
  142. {
  143.     if ( le->leBounceSoundType == LEBS_BRASS ) 
  144.     {
  145.     }
  146.  
  147.     // don't allow a fragment to make multiple bounce sounds,
  148.     // or it gets too noisy as they settle
  149.     le->leBounceSoundType = LEBS_NONE;
  150. }
  151.  
  152.  
  153. /*
  154. ================
  155. CG_ReflectVelocity
  156. ================
  157. */
  158. void CG_ReflectVelocity( localEntity_t *le, trace_t *trace ) {
  159.     vec3_t    velocity;
  160.     float    dot;
  161.     int        hitTime;
  162.  
  163.     // reflect the velocity on the trace plane
  164.     hitTime = cg.time - cg.frametime + cg.frametime * trace->fraction;
  165.     BG_EvaluateTrajectoryDelta( &le->pos, hitTime, velocity );
  166.     dot = DotProduct( velocity, trace->plane.normal );
  167.     VectorMA( velocity, -2*dot, trace->plane.normal, le->pos.trDelta );
  168.  
  169.     VectorScale( le->pos.trDelta, le->bounceFactor, le->pos.trDelta );
  170.  
  171.     VectorCopy( trace->endpos, le->pos.trBase );
  172.     le->pos.trTime = cg.time;
  173.  
  174.  
  175.     // check for stop, making sure that even on low FPS systems it doesn't bobble
  176.     if ( trace->allsolid || 
  177.         ( trace->plane.normal[2] > 0 && 
  178.         ( le->pos.trDelta[2] < 40 || le->pos.trDelta[2] < -cg.frametime * le->pos.trDelta[2] ) ) ) {
  179.         le->pos.trType = TR_STATIONARY;
  180.     } else {
  181.  
  182.     }
  183. }
  184.  
  185. /*
  186. ================
  187. CG_AddFragment
  188. ================
  189. */
  190. void CG_AddFragment( localEntity_t *le ) {
  191.     vec3_t    newOrigin;
  192.     trace_t    trace;
  193.  
  194.     if ( le->pos.trType == TR_STATIONARY ) {
  195.         // sink into the ground if near the removal time
  196.         int        t;
  197.         float    oldZ;
  198.         
  199.         t = le->endTime - cg.time;
  200.         if ( t < SINK_TIME ) {
  201.             // we must use an explicit lighting origin, otherwise the
  202.             // lighting would be lost as soon as the origin went
  203.             // into the ground
  204.             VectorCopy( le->refEntity.origin, le->refEntity.lightingOrigin );
  205.             le->refEntity.renderfx |= RF_LIGHTING_ORIGIN;
  206.             oldZ = le->refEntity.origin[2];
  207.             le->refEntity.origin[2] -= 16 * ( 1.0 - (float)t / SINK_TIME );
  208.             trap_R_AddRefEntityToScene( &le->refEntity );
  209.             le->refEntity.origin[2] = oldZ;
  210.         } else {
  211.             trap_R_AddRefEntityToScene( &le->refEntity );
  212.         }
  213.  
  214.         return;
  215.     }
  216.  
  217.     // calculate new position
  218.     BG_EvaluateTrajectory( &le->pos, cg.time, newOrigin );
  219.  
  220.     // trace a line from previous position to new position
  221.     CG_Trace( &trace, le->refEntity.origin, NULL, NULL, newOrigin, -1, CONTENTS_SOLID );
  222.  
  223.     if ( trace.fraction == 1.0 ) {
  224.         // still in free fall
  225.         VectorCopy( newOrigin, le->refEntity.origin );
  226.  
  227.         if ( le->leFlags & LEF_TUMBLE ) {
  228.             vec3_t angles;
  229.  
  230.             BG_EvaluateTrajectory( &le->angles, cg.time, angles );
  231.             AnglesToAxis( angles, le->refEntity.axis );
  232.         }
  233.  
  234.         trap_R_AddRefEntityToScene( &le->refEntity );
  235.         return;
  236.     }
  237.  
  238.     // if it is in a nodrop zone, remove it
  239.     // this keeps gibs from waiting at the bottom of pits of death
  240.     // and floating levels
  241.     if ( trap_CM_PointContents( trace.endpos, 0 ) & CONTENTS_NODROP ) 
  242.     {
  243.         CG_FreeLocalEntity( le );
  244.         return;
  245.     }
  246.  
  247.     if (!trace.startsolid)
  248.     {
  249.         // leave a mark
  250.         CG_FragmentBounceMark( le, &trace );
  251.  
  252.         // do a bouncy sound
  253.         CG_FragmentBounceSound( le, &trace );
  254.  
  255.         // reflect the velocity on the trace plane
  256.         CG_ReflectVelocity( le, &trace );
  257.  
  258.         trap_R_AddRefEntityToScene( &le->refEntity );
  259.     }
  260. }
  261.  
  262. /*
  263. =====================================================================
  264.  
  265. TRIVIAL LOCAL ENTITIES
  266.  
  267. These only do simple scaling or modulation before passing to the renderer
  268. =====================================================================
  269. */
  270.  
  271. /*
  272. ====================
  273. CG_AddFadeRGB
  274. ====================
  275. */
  276. void CG_AddFadeRGB( localEntity_t *le ) {
  277.     refEntity_t *re;
  278.     float c;
  279.  
  280.     re = &le->refEntity;
  281.  
  282.     c = ( le->endTime - cg.time ) * le->lifeRate;
  283.     c *= 0xff;
  284.  
  285.     re->shaderRGBA[0] = le->color[0] * c;
  286.     re->shaderRGBA[1] = le->color[1] * c;
  287.     re->shaderRGBA[2] = le->color[2] * c;
  288.     re->shaderRGBA[3] = le->color[3] * c;
  289.  
  290.     trap_R_AddRefEntityToScene( re );
  291. }
  292.  
  293. /*
  294. ==================
  295. CG_AddMoveScaleFade
  296. ==================
  297. */
  298. static void CG_AddMoveScaleFade( localEntity_t *le ) {
  299.     refEntity_t    *re;
  300.     float        c;
  301.     vec3_t        delta;
  302.     float        len;
  303.  
  304.     re = &le->refEntity;
  305.  
  306.     if ( le->fadeInTime > le->startTime && cg.time < le->fadeInTime ) {
  307.         // fade / grow time
  308.         c = 1.0 - (float) ( le->fadeInTime - cg.time ) / ( le->fadeInTime - le->startTime );
  309.     }
  310.     else {
  311.         // fade / grow time
  312.         c = ( le->endTime - cg.time ) * le->lifeRate;
  313.     }
  314.  
  315.     re->shaderRGBA[3] = 0xff * c * le->color[3];
  316.  
  317.     if ( !( le->leFlags & LEF_PUFF_DONT_SCALE ) ) {
  318.         re->radius = le->radius * ( 1.0 - c ) + 8;
  319.     }
  320.  
  321.     BG_EvaluateTrajectory( &le->pos, cg.time, re->origin );
  322.  
  323.     // if the view would be "inside" the sprite, kill the sprite
  324.     // so it doesn't add too much overdraw
  325.     VectorSubtract( re->origin, cg.refdef.vieworg, delta );
  326.     len = VectorLength( delta );
  327.     if ( len < le->radius ) {
  328.         CG_FreeLocalEntity( le );
  329.         return;
  330.     }
  331.  
  332.     trap_R_AddRefEntityToScene( re );
  333. }
  334.  
  335. /*
  336. ===================
  337. CG_AddScaleFade
  338.  
  339. For rocket smokes that hang in place, fade out, and are
  340. removed if the view passes through them.
  341. There are often many of these, so it needs to be simple.
  342. ===================
  343. */
  344. static void CG_AddScaleFade( localEntity_t *le ) {
  345.     refEntity_t    *re;
  346.     float        c;
  347.     vec3_t        delta;
  348.     float        len;
  349.  
  350.     re = &le->refEntity;
  351.  
  352.     // fade / grow time
  353.     c = ( le->endTime - cg.time ) * le->lifeRate;
  354.  
  355.     re->shaderRGBA[3] = 0xff * c * le->color[3];
  356.     re->radius = le->radius * ( 1.0 - c ) + 8;
  357.  
  358.     // if the view would be "inside" the sprite, kill the sprite
  359.     // so it doesn't add too much overdraw
  360.     VectorSubtract( re->origin, cg.refdef.vieworg, delta );
  361.     len = VectorLength( delta );
  362.     if ( len < le->radius ) {
  363.         CG_FreeLocalEntity( le );
  364.         return;
  365.     }
  366.  
  367.     trap_R_AddRefEntityToScene( re );
  368. }
  369.  
  370.  
  371. /*
  372. =================
  373. CG_AddFallScaleFade
  374.  
  375. This is just an optimized CG_AddMoveScaleFade
  376. For blood mists that drift down, fade out, and are
  377. removed if the view passes through them.
  378. There are often 100+ of these, so it needs to be simple.
  379. =================
  380. */
  381. static void CG_AddFallScaleFade( localEntity_t *le ) {
  382.     refEntity_t    *re;
  383.     float        c;
  384.     vec3_t        delta;
  385.     float        len;
  386.  
  387.     re = &le->refEntity;
  388.  
  389.     // fade time
  390.     c = ( le->endTime - cg.time ) * le->lifeRate;
  391.  
  392.     re->shaderRGBA[3] = 0xff * c * le->color[3];
  393.  
  394.     re->origin[2] = le->pos.trBase[2] - ( 1.0 - c ) * le->pos.trDelta[2];
  395.  
  396.     re->radius = le->radius * ( 1.0 - c ) + 16;
  397.  
  398.     // if the view would be "inside" the sprite, kill the sprite
  399.     // so it doesn't add too much overdraw
  400.     VectorSubtract( re->origin, cg.refdef.vieworg, delta );
  401.     len = VectorLength( delta );
  402.     if ( len < le->radius ) {
  403.         CG_FreeLocalEntity( le );
  404.         return;
  405.     }
  406.  
  407.     trap_R_AddRefEntityToScene( re );
  408. }
  409.  
  410. /*
  411. ===================
  412. CG_AddRefEntity
  413. ===================
  414. */
  415. void CG_AddRefEntity( localEntity_t *le ) 
  416. {
  417.     if (le->endTime < cg.time) 
  418.     {
  419.         CG_FreeLocalEntity( le );
  420.         return;
  421.     }
  422.     trap_R_AddRefEntityToScene( &le->refEntity );
  423. }
  424.  
  425.  
  426. /*
  427. ===================
  428. CG_AddLine
  429. ===================
  430. */
  431. void CG_AddLine( localEntity_t *le )
  432. {
  433.     refEntity_t    *re;
  434.  
  435.     re = &le->refEntity;
  436.  
  437.     re->reType = RT_LINE;
  438.  
  439.     trap_R_AddRefEntityToScene( re );
  440. }
  441.  
  442. /*
  443. ================
  444. CG_AddGib
  445. ================
  446. */
  447. void CG_AddGib( localEntity_t *le ) {
  448.     vec3_t    newOrigin;
  449.     trace_t    trace;
  450.  
  451.     if ( le->pos.trType == TR_STATIONARY ) {
  452.         // sink into the ground if near the removal time
  453.         int        t;
  454.         float    oldZ;
  455.         
  456.         le->refEntity.origin[2] += le->zOffset;
  457.         t = le->endTime - cg.time;
  458.         if ( t < SINK_TIME ) {
  459.             // we must use an explicit lighting origin, otherwise the
  460.             // lighting would be lost as soon as the origin went
  461.             // into the ground
  462.             VectorCopy( le->refEntity.origin, le->refEntity.lightingOrigin );
  463.             le->refEntity.renderfx |= RF_LIGHTING_ORIGIN;
  464.             oldZ = le->refEntity.origin[2];
  465.             le->refEntity.origin[2] -= 16 * ( 1.0 - (float)t / SINK_TIME );
  466.             trap_R_AddRefEntityToScene( &le->refEntity );
  467.             le->refEntity.origin[2] = oldZ;
  468.         } else {
  469.             trap_R_AddRefEntityToScene( &le->refEntity );
  470.         }
  471.         le->refEntity.origin[2] -= le->zOffset;
  472.  
  473.         return;
  474.     }
  475.  
  476.     // calculate new position
  477.     BG_EvaluateTrajectory( &le->pos, cg.time, newOrigin );
  478.  
  479.     // trace a line from previous position to new position
  480.     CG_Trace( &trace, le->refEntity.origin, NULL, NULL, newOrigin, -1, CONTENTS_SOLID );
  481.     if ( trace.fraction == 1.0 ) {
  482.         // still in free fall
  483.         VectorCopy( newOrigin, le->refEntity.origin );
  484.  
  485.         if ( le->leFlags & LEF_TUMBLE ) {
  486.             vec3_t angles;
  487.  
  488.             BG_EvaluateTrajectory( &le->angles, cg.time, angles );
  489.             AnglesToAxis( angles, le->refEntity.axis );
  490.         }
  491.  
  492.         le->refEntity.origin[2] += le->zOffset;
  493.         trap_R_AddRefEntityToScene( &le->refEntity );
  494.         le->refEntity.origin[2] -= le->zOffset;
  495.  
  496.         return;
  497.     }
  498.  
  499.     // if it is in a nodrop zone, remove it
  500.     // this keeps gibs from waiting at the bottom of pits of death
  501.     // and floating levels
  502.     if ( trap_CM_PointContents( trace.endpos, 0 ) & CONTENTS_NODROP ) 
  503.     {
  504.         CG_FreeLocalEntity( le );
  505.         return;
  506.     }
  507.  
  508.     if (!trace.startsolid)
  509.     {
  510.         // leave a mark
  511. //        CG_FragmentBounceMark( le, &trace );
  512.  
  513.         // do a bouncy sound
  514. //        CG_FragmentBounceSound( le, &trace );
  515.  
  516.         // reflect the velocity on the trace plane
  517.         CG_ReflectVelocity( le, &trace );
  518.  
  519.         le->refEntity.origin[2] += le->zOffset;
  520.         trap_R_AddRefEntityToScene( &le->refEntity );
  521.         le->refEntity.origin[2] -= le->zOffset;
  522.     }
  523. }
  524.  
  525. //==============================================================================
  526.  
  527. /*
  528. ===================
  529. CG_AddLocalEntities
  530. ===================
  531. */
  532. void CG_AddLocalEntities( void ) 
  533. {
  534.     localEntity_t    *le, *next;
  535.  
  536.     // walk the list backwards, so any new local entities generated
  537.     // (trails, marks, etc) will be present this frame
  538.     le = cg_activeLocalEntities.prev;
  539.     for ( ; le != &cg_activeLocalEntities ; le = next ) 
  540.     {
  541.         // grab next now, so if the local entity is freed we
  542.         // still have it
  543.         next = le->prev;
  544.  
  545.         if ( cg.time >= le->endTime ) 
  546.         {
  547.             CG_FreeLocalEntity( le );
  548.             continue;
  549.         }
  550.  
  551.         switch ( le->leType ) 
  552.         {
  553.             default:
  554.                 Com_Error( ERR_FATAL, "Bad leType: %i", le->leType );
  555.                 break;
  556.  
  557.             case LE_FRAGMENT:
  558.                 CG_AddFragment( le );
  559.                 break;
  560.  
  561.             case LE_MOVE_SCALE_FADE:
  562.                 CG_AddMoveScaleFade( le );
  563.                 break;
  564.  
  565.             case LE_FADE_RGB:
  566.                 CG_AddFadeRGB( le );
  567.                 break;
  568.  
  569.             case LE_FALL_SCALE_FADE:
  570.                 CG_AddFallScaleFade( le );
  571.                 break;
  572.  
  573.             case LE_SCALE_FADE:
  574.                 CG_AddScaleFade( le );
  575.                 break;
  576.  
  577.             case LE_SHOWREFENTITY:
  578.                 CG_AddRefEntity( le );
  579.                 break;
  580.  
  581.             case LE_LINE:
  582.                 CG_AddLine( le );
  583.                 break;
  584.  
  585.             case LE_GIB:
  586.                 CG_AddGib(le);
  587.                 break;
  588.         }
  589.     }
  590. }
  591.  
  592.  
  593.  
  594.  
  595.